<template>
  <div class="snake-game">
    <div class="game-container">
      <div class="game-header">
        <h3>🐍 贪吃蛇</h3>
        <button @click="exitGame" class="close-button">X</button>
      </div>
      
      <!-- 游戏菜单 -->
      <div v-if="gameState === 'menu'" class="menu-screen">
        <div class="menu-content">
          <h1>🐍 贪吃蛇</h1>
          <div class="menu-stats">
            <p>最高得分: {{ highScore }}</p>
          </div>
          <div class="menu-controls">
            <button @click="startGame" class="start-button">开始游戏</button>
            <button @click="showInstructions" class="instructions-button">游戏说明</button>
          </div>
          <div v-if="showInstruction" class="instructions">
            <h3>游戏说明</h3>
            <ul>
              <li>使用方向键或WASD控制蛇的移动方向</li>
              <li>吃到食物可以增加长度和得分</li>
              <li>避免撞到墙壁或自己的身体</li>
              <li>按P键可以暂停游戏</li>
            </ul>
            <button @click="hideInstructions" class="back-button">返回</button>
          </div>
        </div>
      </div>
      
      <!-- 操作提示 -->
      <div v-if="showControls" class="controls-overlay">
        <div class="controls-content">
          <h2>操作提示</h2>
          <div class="controls-instructions">
            <p>使用 <kbd>方向键</kbd> 或 <kbd>WASD</kbd> 控制蛇的移动</p>
            <p>按 <kbd>P</kbd> 暂停游戏</p>
          </div>
          <div class="controls-timer">
            <p>游戏将在 <span class="timer">3</span> 秒后开始</p>
          </div>
        </div>
      </div>
      
      <!-- 游戏进行中 -->
      <div v-else-if="gameState === 'playing' || gameState === 'paused'" class="game-screen">
        <!-- 游戏区域 -->
        <div class="game-area" ref="gameArea" tabindex="0" @keydown="handleKeyDown">
          <!-- 食物 -->
          <div 
            class="food"
            :style="{
              left: food.x * gridSize + 'px',
              top: food.y * gridSize + 'px'
            }"
          ></div>
          
          <!-- 蛇身 -->
          <div 
            v-for="(segment, index) in snake" 
            :key="index"
            class="snake-segment"
            :class="{ 'snake-head': index === 0 }"
            :style="{
              left: segment.x * gridSize + 'px',
              top: segment.y * gridSize + 'px'
            }"
          ></div>
        </div>
        
        <!-- 游戏信息 -->
        <div class="game-info">
          <div class="info-item">
            <span>得分: {{ score }}</span>
          </div>
          <div class="info-item">
            <span>长度: {{ snake.length }}</span>
          </div>
          <div class="info-item">
            <span>最高分: {{ highScore }}</span>
          </div>
        </div>
        
        <!-- 暂停界面 -->
        <div v-if="gameState === 'paused'" class="pause-overlay">
          <div class="pause-content">
            <h2>游戏暂停</h2>
            <button @click="resumeGame">继续游戏</button>
          </div>
        </div>
      </div>
      
      <!-- 游戏结束 -->
      <div v-else-if="gameState === 'gameOver'" class="game-over-screen">
        <div class="game-over-content">
          <h1>游戏结束</h1>
          <p>最终得分: {{ score }}</p>
          <p v-if="score > highScore" class="new-record">新纪录!</p>
          <div class="game-over-buttons">
            <button @click="restartGame">重新开始</button>
            <button @click="backToMenu">返回菜单</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue'

// 游戏状态
type GameState = 'menu' | 'playing' | 'paused' | 'gameOver'

// 游戏对象接口
interface Position {
  x: number
  y: number
}

// 游戏常量
const GRID_SIZE = 20
const GAME_WIDTH = 480
const GAME_HEIGHT = 700
const GRID_WIDTH = GAME_WIDTH / GRID_SIZE
const GRID_HEIGHT = GAME_HEIGHT / GRID_SIZE

// 游戏状态
const gameState = ref<GameState>('menu')
const showInstruction = ref(false)
const showControls = ref(false)
const highScore = ref(0)
const gameArea = ref<HTMLElement | null>(null)

// 游戏对象
const snake = reactive<Position[]>([
  { x: 10, y: 10 },
  { x: 9, y: 10 },
  { x: 8, y: 10 }
])
const food = reactive<Position>({ x: 5, y: 5 })
const direction = ref<'UP' | 'DOWN' | 'LEFT' | 'RIGHT'>('RIGHT')
const nextDirection = ref<'UP' | 'DOWN' | 'LEFT' | 'RIGHT'>('RIGHT')

// 游戏数据
const score = ref(0)
const speed = ref(150) // 毫秒

// 游戏定时器
let gameLoopId: number | null = null
let startGameTimer: number | null = null

// 计算属性
const gridSize = GRID_SIZE

// 辅助函数：聚焦游戏区域
const focusGameArea = () => {
  nextTick(() => {
    if (gameArea.value) {
      gameArea.value.focus()
    }
  })
}

// 生成食物
const generateFood = () => {
  let newFood: Position
  let overlapping: boolean
  
  do {
    overlapping = false
    newFood = {
      x: Math.floor(Math.random() * GRID_WIDTH),
      y: Math.floor(Math.random() * GRID_HEIGHT)
    }
    
    // 检查食物是否与蛇身重叠
    for (const segment of snake) {
      if (segment.x === newFood.x && segment.y === newFood.y) {
        overlapping = true
        break
      }
    }
    
    if (!overlapping) {
      food.x = newFood.x
      food.y = newFood.y
    }
  } while (overlapping)
}

// 方法
const startGame = () => {
  // 显示操作提示
  showControls.value = true
  
  // 清除可能存在的定时器
  if (startGameTimer) {
    clearTimeout(startGameTimer)
  }
  
  // 3秒后开始游戏
  startGameTimer = window.setTimeout(() => {
    showControls.value = false
    // 重置游戏状态
    gameState.value = 'playing'
    score.value = 0
    snake.length = 0
    snake.push({ x: 10, y: 10 }, { x: 9, y: 10 }, { x: 8, y: 10 })
    direction.value = 'RIGHT'
    nextDirection.value = 'RIGHT'
    speed.value = 150
    generateFood()
    
    // 开始游戏循环
    startGameLoop()
    
    // 确保游戏区域获取焦点
    focusGameArea()
  }, 3000)
}

const backToMenu = () => {
  gameState.value = 'menu'
  stopGameLoop()
  showControls.value = false
  if (startGameTimer) {
    clearTimeout(startGameTimer)
    startGameTimer = null
  }
}

const exitGame = () => {
  stopGameLoop()
  showControls.value = false
  if (startGameTimer) {
    clearTimeout(startGameTimer)
    startGameTimer = null
  }
  // 通知父组件关闭游戏
  emit('close')
}

const showInstructions = () => {
  showInstruction.value = true
}

const hideInstructions = () => {
  showInstruction.value = false
}

const pauseGame = () => {
  if (gameState.value === 'playing') {
    gameState.value = 'paused'
    stopGameLoop()
  }
}

const resumeGame = () => {
  if (gameState.value === 'paused') {
    gameState.value = 'playing'
    startGameLoop()
    // 恢复游戏时重新获取焦点
    focusGameArea()
  }
}

const restartGame = () => {
  stopGameLoop()
  startGame()
}

const gameOver = () => {
  gameState.value = 'gameOver'
  stopGameLoop()
  
  // 更新最高分
  if (score.value > highScore.value) {
    highScore.value = score.value
    localStorage.setItem('snakeHighScore', highScore.value.toString())
  }
}

// 游戏循环
const startGameLoop = () => {
  stopGameLoop()
  gameLoopId = window.setTimeout(gameLoop, speed.value)
}

const stopGameLoop = () => {
  if (gameLoopId) {
    clearTimeout(gameLoopId)
    gameLoopId = null
  }
}

const gameLoop = () => {
  if (gameState.value !== 'playing') return
  
  moveSnake()
  checkCollision()
  
  gameLoopId = window.setTimeout(gameLoop, speed.value)
}

// 移动蛇
const moveSnake = () => {
  // 更新方向
  direction.value = nextDirection.value
  
  // 创建新头部
  const head = { ...snake[0] }
  
  // 根据方向移动头部
  switch (direction.value) {
    case 'UP':
      head.y -= 1
      break
    case 'DOWN':
      head.y += 1
      break
    case 'LEFT':
      head.x -= 1
      break
    case 'RIGHT':
      head.x += 1
      break
  }
  
  // 将新头部添加到蛇身
  snake.unshift(head)
  
  // 检查是否吃到食物
  if (head.x === food.x && head.y === food.y) {
    // 增加分数
    score.value += 10
    
    // 每50分增加速度
    if (score.value % 50 === 0 && speed.value > 50) {
      speed.value -= 10
    }
    
    // 生成新食物
    generateFood()
  } else {
    // 移除尾部
    snake.pop()
  }
}

// 检查碰撞
const checkCollision = () => {
  const head = snake[0]
  
  // 检查是否撞墙
  if (
    head.x < 0 || 
    head.x >= GRID_WIDTH || 
    head.y < 0 || 
    head.y >= GRID_HEIGHT
  ) {
    gameOver()
    return
  }
  
  // 检查是否撞到自己
  for (let i = 1; i < snake.length; i++) {
    if (head.x === snake[i].x && head.y === snake[i].y) {
      gameOver()
      return
    }
  }
}

// 键盘事件处理
const handleKeyDown = (e: KeyboardEvent) => {
  // 防止默认行为
  e.preventDefault()
  
  // 暂停/继续游戏
  if (e.key === 'p' || e.key === 'P') {
    if (gameState.value === 'playing') {
      pauseGame()
    } else if (gameState.value === 'paused') {
      resumeGame()
    }
    return
  }
  
  // 只在游戏进行时处理方向键
  if (gameState.value !== 'playing') return
  
  // 更新下一个方向，防止反向移动
  switch (e.key) {
    case 'ArrowUp':
    case 'w':
    case 'W':
      if (direction.value !== 'DOWN') {
        nextDirection.value = 'UP'
      }
      break
    case 'ArrowDown':
    case 's':
    case 'S':
      if (direction.value !== 'UP') {
        nextDirection.value = 'DOWN'
      }
      break
    case 'ArrowLeft':
    case 'a':
    case 'A':
      if (direction.value !== 'RIGHT') {
        nextDirection.value = 'LEFT'
      }
      break
    case 'ArrowRight':
    case 'd':
    case 'D':
      if (direction.value !== 'LEFT') {
        nextDirection.value = 'RIGHT'
      }
      break
  }
}

// 组件挂载和卸载
onMounted(() => {
  // 从localStorage获取最高分
  const savedHighScore = localStorage.getItem('snakeHighScore')
  if (savedHighScore) {
    highScore.value = parseInt(savedHighScore)
  }
})

onUnmounted(() => {
  stopGameLoop()
  
  // 清除可能存在的定时器
  if (startGameTimer) {
    clearTimeout(startGameTimer)
  }
})

// 事件发射
const emit = defineEmits(['close'])
</script>

<style scoped>
.snake-game {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.8);
  z-index: 2000;
  display: flex;
  justify-content: center;
  align-items: center;
}

.game-container {
  width: 500px;
  height: 750px;
  background: #1a1a2e;
  border: 3px solid #44bd32;
  border-radius: 10px;
  box-shadow: 0 0 20px rgba(68, 189, 50, 0.5);
  overflow: hidden;
  position: relative;
}

.game-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  background: #16213e;
  color: white;
}

.game-header h3 {
  margin: 0;
  font-size: 1.2rem;
}

.close-button {
  background: #ff4d4d;
  color: white;
  border: none;
  border-radius: 50%;
  width: 30px;
  height: 30px;
  cursor: pointer;
  font-weight: bold;
}

.menu-screen {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: white;
  background: linear-gradient(135deg, #1a1a2e, #16213e);
}

.menu-content h1 {
  font-size: 2.5rem;
  margin-bottom: 20px;
  color: #44bd32;
  text-shadow: 0 0 10px rgba(68, 189, 50, 0.5);
}

.menu-stats {
  margin-bottom: 30px;
  font-size: 1.2rem;
}

.menu-controls {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.menu-controls button {
  padding: 12px 30px;
  font-size: 1.1rem;
  border: none;
  border-radius: 30px;
  cursor: pointer;
  transition: all 0.3s;
  font-weight: bold;
}

.start-button {
  background: linear-gradient(to right, #00b09b, #96c93d);
  color: white;
}

.instructions-button {
  background: linear-gradient(to right, #2193b0, #6dd5ed);
  color: white;
}

.menu-controls button:hover {
  transform: scale(1.05);
  box-shadow: 0 0 15px rgba(255, 255, 255, 0.3);
}

.instructions {
  background: rgba(0, 0, 0, 0.8);
  padding: 20px;
  border-radius: 10px;
  margin-top: 20px;
  max-width: 80%;
}

.instructions h3 {
  color: #44bd32;
  margin-top: 0;
}

.instructions ul {
  text-align: left;
  padding-left: 20px;
}

.instructions li {
  margin-bottom: 10px;
}

.back-button {
  background: #ff6b6b;
  color: white;
  border: none;
  padding: 8px 20px;
  border-radius: 20px;
  cursor: pointer;
  margin-top: 15px;
}

.controls-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.85);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 2001;
  color: white;
}

.controls-content {
  text-align: center;
  padding: 30px;
  background: #1a1a2e;
  border-radius: 15px;
  border: 2px solid #44bd32;
  max-width: 80%;
}

.controls-content h2 {
  color: #44bd32;
  margin-top: 0;
  font-size: 2rem;
}

.controls-instructions {
  margin: 25px 0;
  font-size: 1.2rem;
}

.controls-instructions p {
  margin: 15px 0;
}

.controls-instructions kbd {
  background: #333;
  color: #fff;
  padding: 3px 8px;
  border-radius: 4px;
  box-shadow: 0 2px 0 rgba(0,0,0,0.2);
  font-family: monospace;
}

.controls-timer {
  font-size: 1.1rem;
  margin-top: 20px;
}

.controls-timer .timer {
  color: #44bd32;
  font-weight: bold;
  font-size: 1.3rem;
}

.game-screen {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.game-area {
  width: 480px;
  height: 700px;
  background: linear-gradient(180deg, #0c1445 0%, #1a1a2e 100%);
  position: relative;
  outline: none;
  overflow: hidden;
}

/* 蛇身 */
.snake-segment {
  position: absolute;
  width: 18px;
  height: 18px;
  background: linear-gradient(45deg, #44bd32, #0097e6);
  border: 1px solid #0097e6;
  border-radius: 4px;
  z-index: 5;
}

.snake-head {
  background: linear-gradient(45deg, #0097e6, #44bd32);
  border: 1px solid #fbc531;
  box-shadow: 0 0 10px #0097e6;
}

/* 食物 */
.food {
  position: absolute;
  width: 18px;
  height: 18px;
  background: linear-gradient(45deg, #e84118, #fbc531);
  border-radius: 50%;
  z-index: 5;
  box-shadow: 0 0 10px #e84118;
  animation: pulse 1s infinite;
}

@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.2); }
}

.game-info {
  display: flex;
  justify-content: space-around;
  padding: 10px;
  background: #16213e;
  color: white;
  font-weight: bold;
}

.info-item {
  display: flex;
  align-items: center;
  gap: 5px;
}

.pause-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 100;
}

.pause-content {
  background: #1a1a2e;
  padding: 30px;
  border-radius: 10px;
  text-align: center;
  color: white;
}

.pause-content h2 {
  margin-top: 0;
  color: #44bd32;
}

.pause-content button {
  background: #44bd32;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 1rem;
}

.game-over-screen {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background: linear-gradient(135deg, #1a1a2e, #16213e);
  color: white;
}

.game-over-content {
  text-align: center;
  padding: 30px;
  background: rgba(0, 0, 0, 0.7);
  border-radius: 15px;
}

.game-over-content h1 {
  color: #ff6b6b;
  margin-top: 0;
}

.new-record {
  color: #f1c40f;
  font-weight: bold;
  font-size: 1.2rem;
}

.game-over-buttons {
  display: flex;
  gap: 20px;
  justify-content: center;
  margin-top: 20px;
}

.game-over-buttons button {
  padding: 12px 25px;
  border: none;
  border-radius: 30px;
  cursor: pointer;
  font-weight: bold;
  transition: all 0.3s;
}

.game-over-buttons button:first-child {
  background: linear-gradient(to right, #00b09b, #96c93d);
  color: white;
}

.game-over-buttons button:last-child {
  background: linear-gradient(to right, #2193b0, #6dd5ed);
  color: white;
}

.game-over-buttons button:hover {
  transform: scale(1.05);
}
</style>